#include <iostream>
#include <atomic>
#include <thread>

template <typename T>
class SharedPtr {
public:
  explicit SharedPtr(T* ptr = nullptr) : ptr_(ptr), count_(1) {
    std::cout <<"SharedPtr constructed\n";
  }

  SharedPtr(const SharedPtr<T>& other) : ptr_(other.ptr_), count_(other.count_) {
    add_ref();
    std::cout << "SharedPtr copied\n";
  }

  SharedPtr<T>& operator=(const SharedPtr<T> &other) {
    if (this != &other) {
      release();
      ptr_ = other.ptr_;
      count_ = other.count_;
      add_ref();
    }
    return *this;
  }

  ~SharedPtr() {
    release();
    std::cout << "SharedPtr destructed\n";
  }

  T* get() const {
    return ptr_;
  }

  // 重置指针
    void reset(T* ptr = nullptr) {
        SharedPtr<T>(ptr).swap(*this);
    }

    // 交换指针
    void swap(SharedPtr<T>& other) {
        std::swap(ptr_, other.ptr_);
        unsigned long tempCount = count_.load(std::memory_order_acquire);
        count_.store(other.count_.load(std::memory_order_acquire), std::memory_order_release);
        other.count_.store(tempCount, std::memory_order_release);
    }

  void add_ref() {
    count_.fetch_add(1, std::memory_order_acq_rel);
  }

  void release() {
    if (ptr_ && count_.fetch_sub(1, std::memory_order_acq_rel) == 1) {
      delete ptr_;
    }
  }

private:
  T* ptr_;
  std::atomic<unsigned long> count_;
};

int main() {
    SharedPtr<int> ptr1(new int(42));
    SharedPtr<int> ptr2 = ptr1; // 拷贝构造

    SharedPtr<int> ptr3;
    ptr3 = ptr2; // 赋值

    std::cout << *ptr1.get() << std::endl;

    // 测试线程安全性
    ptr1.reset(new int(100));
    std::thread t1([&] { ptr1.reset(new int(200)); });
    std::thread t2([&] { ptr2.reset(new int(300)); });
    t1.join();
    t2.join();

    std::cout << *ptr1.get() << std::endl;
    std::cout << *ptr2.get() << std::endl;

    return 0;
}